A relational database stores data in a structured way. In particular, a relational database is made up of one or more tables, each table divided into rows each representing a different data item and columns each representing a different kind of information about each data item. Within a table, data is stored in fields that each constitute the intersection of one row with one column. The set of columns in a particular table and their types are said to constitute that table's schema, while the schemas of a database's tables together with the identities of those tables are collectively said to constitute the database's schema. The database's schema is also sometimes referred to as its “database model” or “data model.”
Object-relational mapping is a technique for making the contents of a relational database accessible for retrieval and modification by an object-oriented computer program. The mapping effectively creates a virtual object database that can be used from within and object-oriented program. While it's possible for data available from this virtual object database to include all of the data contained by the relational database, in many cases the virtual object database is defined based on a query against the relational database that selects certain of its rows and columns, and optionally performs transformations on them.
To implement object-relational mapping, an object oriented programming language is used to express an object relational model (also “ORM” or “object model” herein) that is mapped to a data model of a relational database. Operations on the data are then conducted according to the object model. In particular, database commands are not issued directly to the database. Instead, object methods are executed within the object model and values are changed within the object model. When a query is made for the relational database or changes to the data are made, those queries and changes are translated to database commands, and those commands are sent to the database.
A type class (or “object”) is the root of the object model. A type class represents type declarations: class types, interface types, array types, value types, enumeration types, type parameters, generic type definitions, and open or closed constructed generic types. The members of the type class are used to get information about a type declaration, such as constructors, methods, fields, properties, and events of a class, in addition to the module and assembly in which the class is deployed.
An object model may have an entity class, class member, association, and method that map to a database model having a table, field, foreign key relationship, and stored procedure or function, respectively. In this example, a database table is represented by an entity class. A foreign key relationship defines a relationship between two database tables with a primary-key identified in a first table (or a field in the first table) and a foreign-key identified in another table (or a field or multiple fields in another table).
Entity objects (or simply “entities”) have properties (or “attributes”), methods (also called “functions”), and data. A property may have an accessor that contains executable statements associated with getting (or “reading”) or setting (or “writing”) the property. Thus, an accessor is used to obtain data from the database.
Entity objects may have expressions or expression trees that represent a node in a tree-like data structure. Each node is an expression (i.e., a method call or an operation). Code represented by expression trees can be compiled, which enables dynamic modification of executable code, the execution of queries and databases, and the creation of queries.
A lambda expression is one of any number of expressions (and expression types) that is used to build an expression tree. A lambda expression is a means of defining an abstract algorithm before it is known to what data that algorithm will be applied.
An assembly is a collection of entity types and resources that are built to work together and form a logical unit of functionality. An assembly contains the information needed at runtime so that the application is aware of type implementations.
The type class is the root of the reflection functionality and is the primary way to access metadata. Reflection provides objects that encapsulate assemblies, modules, and types. Reflection can be used to dynamically create an instance of a type (object), bind the type (object) to an existing object, or get the type from an existing object. The type's methods may be invoked or the fields and properties of the type may be accessed.
Some ORM systems contain classes that are used to generate an ORM object model that represents the structure and content of a relational database. These mappings are identified as namespaces. For example, a mapping namespace class (object) may designate a property to represent a database association (such as a foreign-key relationship), a field attribute (to associate a class with a field (column) and a database table), an accessor to a member, a metaassociation to represent an association relationship between two entity types, a mapping between a context method and a database function, a meta-data table to represent an abstraction of a database table view, a meta-data type to represent a mapping of a domain object type to a field (column) of a database table, and other mappings.
One type of namespace is a reflection namespace. The reflection namespace contains the types that retrieve information about assemblies, modules, members, parameters, and other entities by examining their metadata. These types can also be used to manipulate instances of loaded types. For example, a namespace object represents an abstract root object for a data source. Properties can be referenced by namespaces.
A runtime loader manages application domains. This management includes loading each assembly into the appropriate application domain and controlling the memory layout of the type hierarchy within each assembly. Assemblies contain modules, modules contain types, and types contain members.
Rows in a relational database table do not have unique identities. Since each row has a unique primary key, no two rows share the same key value. However, this fact constrains only the contents of the database table.
When a new row is retrieved from a database, the row is logged in an identity table by its primary key, and a new object is created. When that same row is retrieved, the original object instance is handed back to the application. Thus, the data context manages the object identity and translates the concept of identity as seen by the database (e.g., primary key) into the concept of identity accepted by the ORM (e.g., instances). The ORM application only sees the object in the state from which it was first retrieved. An identity table acts as a cache of all previously retrieved objects.
A data context provides the mapping of all object entities to the database model. It is through the data context that the application containing the object entities can query the database. It is through the data context that changes to the database can be implemented.
Data management tasks in object-oriented programming systems typically are implemented by manipulating objects that are almost always non-scalar variables. Scalar variables hold only a single value at a time, whereas non-scalar variables may hold composite variables, such as arrays, lists, hash, records, and other non-scalar variable types.
Many database systems, such as structured query language database management systems and other relational database management systems, can only store or manipulate scalar values, such as integers and strings organized within tables. Thus, ORM systems convert object values from object data structures into groups of simpler values for storage in a database and convert the database values back to object values upon retrieval. The process of retrieving data from a database and mapping the data to an ORM object is sometimes referred to as touching the object.
As mentioned above, an ORM system may be used as a basis to develop an object-oriented program that retrieves and displays a portion of the data in a database, and enable its revision by a user. In some cases, such an application also causes various transformations to be performed on the data before displaying it, either as an integral part of the retrieval or subsequent to the retrieval.
Two conventional approaches may be used to design the particular retrieval and transformation to be performed by such an application. In a first, a programmer specifies a textual query as part of developing the application. Because the textual query is parsed into an expression tree and compiled into a mapped object model, the textual query depends on the schema of the database known at the time the mapped object model is compiled.
In a second conventional approach used to design the particular retrieval and transformation to be performed by such an application, a programmer, as part of developing the application, incorporates into the application a mechanism that enables a non-expert user to visually construct a query by manipulating a visual user interface, such as by using drag-and-drop and/or pull-down selection user interface techniques. The implementation of this user interface similarly depends on the schema of the database known at the time the application is compiled.